﻿using System;
using System.Collections.Generic;
using JetBrains.Annotations;

namespace CxExtension
{
	public static class LinkListExt
	{

		public static void Enqueue<T>([NotNull] this LinkedList<T> self, [NotNull] T t)
		{
			if (self == null) throw new ArgumentNullException("self");
			if (t == null) throw new ArgumentNullException("t");
			self.AddLast(t);
		}

		public static T Dequeue<T>([NotNull] this LinkedList<T> self)
		{
			if (self == null) throw new ArgumentNullException("self");
			if (self.Count == 0)
			{
				return default(T);
			}
			var first = self.First.Value;
			self.RemoveFirst();
			return first;
		}
		public static V GetOrNewAddF<K,V>(this LinkedList<V> self, K k, [NotNull] Func<K,V> newfunc)
		{

			return default(V);
		}

		public static void ForEach<T>(this LinkedList<T> self, [NotNull] Action<T> call)
		{
			if (call == null) throw new ArgumentNullException("call");
			foreach (var it in self)
			{
				call(it);
			}
		}

		/// <summary>
		/// 出栈所有的元素
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="self"></param>
		/// <param name="call"></param>
		public static void DequeueAll<T>(this LinkedList<T> self, [NotNull] Action<T> call)
		{
			self.ForEachSafe(call);
			self.Clear();
		}
		/// <summary>
		/// 遍历所有元素,可以在遍历过程中删除元素
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="self"></param>
		/// <param name="call"></param>
		public static void ForEachSafe<T>(this LinkedList<T> self, [NotNull] Action<T> call)
		{
			if (self.Count == 0)
			{
				return;
			}

			LinkedListNode<T> next = self.First;
			do
			{
				var cur = next;
				next = cur.Next;
				call(cur.Value);

			} while (next != null);
			
		}
		public static void ForEachNodeSafe<T>(this LinkedList<T> self, [NotNull] Action<LinkedListNode<T>> call)
		{
			if (self.Count == 0)
			{
				return;
			}

			var next = self.First;
			do
			{
				var cur = next;
				next = cur.Next;
				call(cur);

			} while (next != null);

		}

		public static void ForEachRemoveAll<T>(this LinkedList<T> self, [NotNull] Func<T, bool> call)
		{
			self.ForEachSafe(call,self.Remove_bool);
		}

		internal static bool Remove_bool<T>(this LinkedList<T> self,LinkedListNode<T> it)
		{
			self.Remove(it);
			return false;
		}
		/// <summary>
		/// if call return true then 调用 selectAction,
		/// then if selectAction return true then break loop
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="self"></param>
		/// <param name="call"></param>
		/// <param name="selectAction">if call return true then call selectAction,
		/// if selectAction return true break the foreach</param>
		public static void ForEachSafe<T>(this LinkedList<T> self, [NotNull] Func<T, bool> call, [NotNull] Func<LinkedListNode<T>,bool> selectAction)
		{
			if (selectAction == null) throw new ArgumentNullException("selectAction");
			if (self.Count == 0)
			{
				return;
			}

			var next = self.First;
			do
			{
				var cur = next;
				next = cur.Next;
				var value = cur.Value;
				if (call(value))
				{
					if (selectAction(cur))
					{
						break;
					}
				}

			} while (next != null);

		}

	}
}